package flca.mda.api.util;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import reactive.Tid;
import flca.mda.codegen.helpers.StrUtil;

public class ReactiveDojoTypeUtils extends ReactiveTypeUtils {

	/**
	 * return a constant like CUSTOMER_RETRIEVE_SUCCESS given a Class Customer
	 * and an Enum ITEM_RETRIEVE_SUCCESS The const values are maintained in
	 * dojo.ini
	 * 
	 * @param aClass
	 * @param aConstantType
	 * @return
	 */
	public String getConstant(Class<?> aClass, ConstType aConstantType) {
		Properties props = new Properties();
		props.put("entity_const", aClass.getSimpleName().toUpperCase());
		String result = StrUtil.subsProperties(CONST_SRV_MAP.get(aConstantType), props);
		if (result == null) {
			result = "?" + aConstantType + "?";
		}
		return result;
	}

	/**
	 * This is a enhanced version of the original
	 * ebappInterfaceUtils.getSubsWithsForCrudOper method. This methods add an
	 * entru for all ConstantsTypes's.
	 * 
	 * @param aClass
	 * @return
	 */
	public Properties getSubsWithsForDojoCrudOper(CrudMethod aCrudMethod) {
		Properties result = getSubsWithsForCrudOper(aCrudMethod, false);

		Class<?> crudent = aCrudMethod.getEntity();

		for (ConstType ctype : ConstType.values()) {
			result.put(ctype.name(), getConstant(crudent, ctype));
		}
		return result;
	}

	public static enum ConstType
	{
		ITEM_RETRIEVE, ITEM_RETRIEVE_SUCCESS, ITEM_RETRIEVE_ERROR, ITEM_SAVE, ITEM_SAVE_SUCCESS, ITEM_SAVE_ERROR, ITEM_FINDALL, ITEM_FINDALL_SUCCESS, ITEM_FINDALL_ERROR, ITEM_SEARCH, ITEM_SEARCH_SUCCESS, ITEM_SEARCH_ERROR, ITEM_REMOVE, ITEM_REMOVE_SUCCESS, ITEM_REMOVE_ERROR, ADD_ITEM, EDIT_ITEM, SHOW_ITEM_GRID, SHOW_ITEM_DETAIL, REMOVE_ITEM_GRID, CLOSE_ITEM_DETAIL, REMOVE_ITEM_DETAIL, DIV_ITEM_DETAIL_ID,
	}

	private static final Map<ConstType, String> CONST_SRV_MAP = new HashMap<ReactiveDojoTypeUtils.ConstType, String>() {
		private static final long serialVersionUID = 3220274762342928563L;
		{
			put(ConstType.ADD_ITEM, "<%=entity_const%>_ADD");
			put(ConstType.EDIT_ITEM, "<%=entity_const%>_EDIT");
			put(ConstType.ITEM_RETRIEVE, "<%=entity_const%>_RETRIEVE");
			put(ConstType.ITEM_RETRIEVE_SUCCESS, "<%=entity_const%>_RETRIEVE_SUCCESS");
			put(ConstType.ITEM_RETRIEVE_ERROR, "<%=entity_const%>_RETRIEVE_ERROR");
			put(ConstType.ITEM_SAVE, "<%=entity_const%>_SAVE");
			put(ConstType.ITEM_SAVE_SUCCESS, "<%=entity_const%>_SAVE_SUCCESS");
			put(ConstType.ITEM_SAVE_ERROR, "<%=entity_const%>_SAVE_ERROR");
			put(ConstType.ITEM_FINDALL, "<%=entity_const%>_FINDALL");
			put(ConstType.ITEM_FINDALL_SUCCESS, "<%=entity_const%>_FINDALL_SUCCESS");
			put(ConstType.ITEM_FINDALL_ERROR, "<%=entity_const%>_FINDALL_ERROR");
			put(ConstType.ITEM_SEARCH, "<%=entity_const%>_SEARCH");
			put(ConstType.ITEM_SEARCH_SUCCESS, "<%=entity_const%>_SEARCH_SUCCESS");
			put(ConstType.ITEM_SEARCH_ERROR, "<%=entity_const%>_SEARCH_ERROR");
			put(ConstType.ITEM_REMOVE, "<%=entity_const%>_REMOVE");
			put(ConstType.ITEM_REMOVE_SUCCESS, "<%=entity_const%>_REMOVE_SUCCESS");
			put(ConstType.ITEM_REMOVE_ERROR, "<%=entity_const%>_REMOVE_ERROR");
		}
	};

	private static final Map<ConstType, String> CONST_GUI_MAP = new HashMap<ReactiveDojoTypeUtils.ConstType, String>() {
		private static final long serialVersionUID = 3220274762342928563L;
		{
			put(ConstType.SHOW_ITEM_GRID, "<%=entity_const%>_SHOW_GRID");
			put(ConstType.SHOW_ITEM_DETAIL, "<%=entity_const%>_SHOW_DETAIL");
			put(ConstType.REMOVE_ITEM_GRID, "<%=entity_const%>_REMOVE_GRID");
			put(ConstType.CLOSE_ITEM_DETAIL, "<%=entity_const%>_CLOSE_DETAIL");
			put(ConstType.REMOVE_ITEM_DETAIL, "<%=entity_const%>_REMOVE_DETAIL");
			put(ConstType.DIV_ITEM_DETAIL_ID, "DIV_<%=entity_const%>_DETAIL_ID");
		}
	};

	/**
	 * return all dojo constants for all entities, with generated line like
	 * A_RETRIEVE : "A_RETRIEVE",
	 * 
	 * @return
	 */
	public String getAllDojoConstants() {
		StringBuffer sb = new StringBuffer();
		List<Class<?>> entities = getAllModelEntities();
		for (Class<?> ent : entities) {
			if (generateRestService(ent)) {
				for (String strval : CONST_SRV_MAP.values()) {
					String s = StrUtil.replace(strval, "<%=entity_const%>", ent.getSimpleName().toUpperCase());
					sb.append(S2 + s + " : \"" + s.toLowerCase() + "\",\n");
				}
			}
			if (hasGuiAnnotation(ent)) {
				for (String strval : CONST_GUI_MAP.values()) {
					String s = StrUtil.replace(strval, "<%=entity_const%>", ent.getSimpleName().toUpperCase());
					sb.append(S2 + s + " : \"" + s.toLowerCase() + "\",\n");
				}
			}
		}
		return sb.toString();
	}

	public String getDefaultValue(Field aField) {
		String result = null;
		if (isPrimitive(aField) || isSimpleField(aField)) {
			result = nu.getIniFileValue("dojo.default-value", getTypeName(aField));
		} else {
			result = "null";
		}

		if (result == null) {
			result = "null";
		}
		return result;
	}

	public String getLabel(Field aField) {
		return aField.getName(); // TODO Label annotation
	}

	private String DONT_SHOW_PROPS[] = new String[] { "id", "parent", "createdAt", "createdBy", "modifiedAt", "modifiedBy", "version",
			"locked", "lockedBy", "lockedAt", };

	/**
	 * Not all properties should be visible on the forms
	 * 
	 * @param property
	 * @return
	 */
	public boolean dontShow(Field aField) {
		for (String s : DONT_SHOW_PROPS) {
			if (s.equals(aField.getName())) {
				return true;
			}
		}
		return false;
	}

	public String getExtendsAndImplements() {
		return ""; // TODO
	}

	public String getExtendsAndImplementsLitteral(Class<?> uml2Class) {
		return ""; // TODO
	}

	/**
	 * 
	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForClass(Field aField) {
		// this will take care of the import
		getTypeName(aField);

		Properties result = new Properties();
		result.put("uncapName", nu.uncapName(aField));
		result.put("capName", nu.capName(aField));
		result.put("type", getTypeName(aField));
		result.put("defValue", getDefaultValue(aField));
		return result;
	}

	/**
	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForDojo(Field aField) {
		Properties result = new Properties();
		result.put("uncapName", nu.uncapName(aField));
		result.put("capName", nu.capName(aField));
		result.put("inputTag", getInputTag(aField));
		result.put("label", getLabel(aField));
		result.put("cssClassname", getCssClassname(aField));
		result.put("maxchars", getMaxChars(aField));
		result.put("required", getRequired(aField));
		result.put("enumClass", getTypeName(aField));
		return result;
	}

	// /**
	// * @param aField
	// * @return
	// */
	// public Properties getSubsWithsForFlexCrudOper(CrudMethod aCrudMethod)
	// {
	// Class<?> crudent = aCrudMethod.getEntity();
	// String entityName = tplu.getClassName(crudent, Tid.SCALAENTITY.name());
	// String pktype = getIdTypeName(crudent);
	//
	// Properties result = new Properties();
	// result.put("entity", entityName);
	// result.put("pkType", pktype);
	// return result;
	// }

	/**
	 * note Enum, One2Manu and Many2One are filtered out before this step
	 * 
	 * @param aField
	 * @return
	 */
	public String getInputTag(Field aField) {
		String result = "TextBox";
		if (isRequired(aField)) {
			result = "ValidationTextBox";
		}

		if (isNumeric(aField)) {
			result = "NumberTextBox";
		} else if (isDate(aField.getType())) {
			result = "DateTextBox";
		} else if (isTime(aField.getType())) {
			result = "TimeTextBox";
		} else if (isBoolean(aField.getType())) {
			result = "CheckBox";
		}
		return result;
	}

	public String getCssClassname(Field aField) {
		return (isRequired(aField)) ? "classname : 'req'" : "classname : 'normal'";
	}

	public boolean isRequired(Field aField) {
		if (vu.mustValidate(aField)) {
			if (vu.isRequired(aField)) {
				return true;
			}
		}

		return false;
	}

	public String getRequired(Field aField) {
		return (isRequired(aField)) ? "true" : "false";
	}

	public String getMaxChars(Field aField) {
		return "";
	}

	public boolean isJoinTable() {
		return false;
	}

	public JoinTableProps[] getJoinTableProps() {
		return new JoinTableProps[] { new JoinTableProps(), new JoinTableProps() };
	}
	
	/**
	 * @param aField
	 * @return
	 */
	public Properties getSubsWithsForCrudOper(CrudMethod aCrudMethod, boolean aForFlex)
	{
		Class<?> crudent = aCrudMethod.getEntity(); 

		String entityName = tplu.getClassName(crudent, Tid.SCALA_ENTITY.name()); 
		String pktype =  getIdTypeName(crudent);
		String validator =  ""; 
		String dao =  "";
		String daoImpl = "";
		String daosrvProp =  "";
		String mock =  ""; 
		String searchArgsDto =  "";
			
		Properties result = new Properties();
		result.put("entity", entityName);
		result.put("pkType", pktype);
		result.put("validator", validator);
		result.put("dao", dao);
		result.put("daoImpl", daoImpl);
		result.put("daosrvProp", daosrvProp);
		result.put("mock", mock);
		result.put("searchDto", searchArgsDto);
		
		return result;
	}
	

}
